<template>
  <div class="rt-container">
    <div class="rt-table" v-if="tableData.rows.length">
      <el-form :model="tableData" :ref="item &&  item.vModel">
        <table cellspacing="0" cellpadding="0" border="0" v-if="dataValue"
               :class="['el-table el-table--border',table.align == 'left' ? 'leftAlign' : (table.align == 'right' ? 'rightAlign' : 'centerAlign')]">
          <tbody>
          <tr>
            <td width="100" class="el-table__cell"/>
            <td v-for="(col,index) in table.columns" :key="index" class="el-table__cell">
              {{ col.label }}
            </td>
          </tr>

          <tr v-for="(row,rIndex) in tableData.rows" :key="rIndex">
            <!-- <el-form-item> -->
            <td class="el-table__cell">
              {{ row.label }}
            </td>

            <td v-for="(col,cIndex) in row.columns" :key="cIndex" :width="col.columnForm.width" class="el-table__cell">
              <!-- 单选多选 -->
              <el-form-item v-if="col.columnForm.type==1" style="margin-bottom:0" label=""
                            :prop="'rows.'+rIndex+'.columns.' + cIndex"
                            :rules="selectRules">
                <el-select
                  @change="(value) =>
                            handleSelectChange(
                              value,
                              col,
                              rIndex,
                              row.id,col.id,
                              col.value
                            )"
                  style="width: 70%;"
                  v-model="col.value"
                  :multiple="col.columnForm.multipleSelect"
                  :multiple-limit='col.columnForm.max'
                  popper-class="t-select-popper"
                >
                  <el-option
                    v-for="(option) in col.columnForm.options"
                    :disabled="option['disabled'+rIndex]"
                    :key="option.value"
                    :value="option"
                    :label="option.label"
                  />
                </el-select>
              </el-form-item>

              <!-- 问答填空 -->
              <el-form-item v-if="col.columnForm.type==2 || col.columnForm.type==3" style="margin-bottom:0" label=""
                            :prop="'rows.'+rIndex+'.columns.' + cIndex"
                            :rules="itemRules">
                <el-input
                  minlength="1"
                  maxlength="200"
                  v-model.trim="col.value"
                  @change="handleInputChange(row.id,col.id,col.value)"
                />
              </el-form-item>
              <!-- 上传文件 -->
              <!-- :prop="'columns.' + cIndex+rIndex" -->
              <el-form-item v-if="col.columnForm.type==4" style="margin-bottom:0" label=""
                            :prop="'rows.'+rIndex+'.columns.' + cIndex"
                            :rules="uploadRules"
              >
                <el-upload
                  v-bind="{...item}"
                  :multiple="col.columnForm.multipleFile"
                  :limit="col.columnForm.multipleFile ? col.columnForm.fileNum : 1"
                  :accept="col.columnForm.fileType || ''"
                  :on-preview="handlePreview"
                  :on-change="(file, fileList) => handleUploadChange(fileList, rIndex, cIndex)"
                  :on-remove="(file, fileList) =>
                          handleRemove(
                            file,
                            fileList,
                            row.id,
                            col.id,
                            'rows.'+rIndex+'.columns.' + cIndex,
                            rIndex,
                            cIndex
                          )"

                  :before-upload="(file, fileList) =>
                          beforeUpload2(
                            file,
                            col,
                            cIndex
                          )"
                  :file-list="col.value2 || []"
                  :on-exceed="(file, fileList) =>
                          handleExceed(col)"
                  :http-request="(file, fileList) =>
                          httpRequest(
                            file,
                            row.id,
                            col.id,
                            'rows.'+rIndex+'.columns.' + cIndex,
                            rIndex,
                            cIndex
                          )"
                >
                  <el-button size="mini" type="primary">
                    上传文件
                  </el-button>

                </el-upload>
              </el-form-item>
            </td>
            <!-- </el-form-item> -->

          </tr>
          </tbody>
        </table>
      </el-form>


    </div>
  </div>
</template>

<script>
import mixin from '../mixin'
import uploadMixin from '../uploadMixin'
import {jsonSimpleClone} from "../../../utils"
import axios from 'axios'
const axiosSourceMap = new Map()
export default {
  name: 'MatrixTable',
  mixins: [mixin, uploadMixin],
  props: {
    table: {
      type: Object,
      default: () => {
      }
    },
  },
  data() {
    let handleUpload = (rule, value, callback) => {
      console.log(value.value, 'upload---value')
      this.$nextTick(function () {
        if (value.columnForm.required) {
          if (value.value && value.value.length) {
            callback()
          } else {
            callback(new Error('请选择'))
          }
        } else {
          callback()
        }
      })
    }
    let handleDuplicate = (rule, value, callback) => {
      console.log(value, 'value填空')
      let validator = ''
      let text = ''
      switch (value.columnForm.testType) {
        case 1:
          validator = ''
          break
        case 2:
          // 阿拉伯数字
          validator = '^[0-9]+$'
          text = "请输入阿拉伯数字格式"
          break
        case 3:
          // 固定电话
          validator = '^[0-9]{3,4}-[0-9]{7,8}$'
          text = "请输入固定电话格式"
          break
        case 4:
          // 手机号
          validator = '^1[3-9][0-9]{9}$'
          text = "请输入手机号格式"
          break
        case 5:
          // 邮政编码
          validator = '^[1-9][0-9]{5}$'
          text = "请输入邮政编码格式"
          break
        case 6:
          // Email
          validator = '^([a-zA-Z0-9]+[-_\.]?)+@[a-zA-Z0-9]+\.[a-z]+$'
          text = "请输入Email格式"
          break
        case 7:
          // URL
          validator = "[a-zA-z]+://[^\s]*";
          // validator = '^(?:(?:https?)://)(?:(?:1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])(?:\.(?:1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)){2}(?:\.(?:1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*)(?::([1-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5]))?(?:/\S*)?$'
          text = "请输入URl格式"
          break
        case 8:
          // 身份证
          validator = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
          text = "请输入身份证格式"
          break
        case 9:
          // 日期
          // 2022-07-08
          validator = '^([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8])))+$'
          text = "请输入日期格式"
          break
        case 10:
          // 中文
          validator = '^[\u4e00-\u9fa5]+$'
          text = "请输入中文格式"
          break
        case 11:
          // 中英文
          validator = '^[\u4e00-\u9fa5a-zA-Z]+$'
          text = "请输入中英文格式"
          break
      }
      if (value.columnForm.required) {
        if (value.value) {
          if (!new RegExp(validator).test(value.value)) {
            callback(new Error(text))
          } else {
            callback()
          }
        } else {
          callback(new Error('请输入内容'))
        }
      } else {
        if (value.value) {
          if (!new RegExp(validator).test(value.value)) {
            callback(new Error(text))
          } else {
            callback()
          }
        } else {
          callback()
        }
      }
    }
    let handleSelect = (rule, value, callback) => {
      console.log(value, 'value')
      this.$nextTick(function () {
        if (value.columnForm.required) {
          if (value.value && _.isArray(value.value) && value.value.length) {
            callback()
          } else if (value.value && value.value['label']) {
            callback()
          } else {
            callback(new Error('请选择'))
          }
        } else {
          callback()
        }
      })
    }
    return {
      values: [],
      dataValue: {},
      selectRules: [{trigger: 'change', validator: handleSelect}],
      itemRules: [{trigger: 'blur', validator: handleDuplicate}],
      uploadRules: [{trigger: 'change', validator: handleUpload}],
      flag: '',
      singleOrAll: true,
      tableData: {
        rows: []
      }
    }
  },
  watch: {
    table: {
      handler(value) {
        this.initValue()
        var table = JSON.parse(JSON.stringify(value))
        console.log(table, 'table-----')
        this.tableData.rows = []
        table.rows.forEach(item => {
          this.$set(item, 'columns', JSON.parse(JSON.stringify(this.table.columns)))
          item.columns.forEach(item2 => {
            // el-select绑定的数据为null，就会触发change事件，从而开启了表单校验
            if (item2.columnForm.type == 1) {
              if (item2.columnForm.multipleSelect) {
                this.$set(item2, 'value', (this.dataValue[item.id][item2.id] == null ? [] : this.dataValue[item.id][item2.id]))
              } else {
                this.$set(item2, 'value', (this.dataValue[item.id][item2.id] == null ? {} : this.dataValue[item.id][item2.id]))
              }
            } else {
              this.$set(item2, 'value', this.dataValue[item.id][item2.id])
              if(item2.columnForm.type == 4){
                this.$set(item2, 'value2', this.dataValue[item.id][item2.id])
              }
            }

          })
          this.tableData.rows.push(item)
        })
      },
      deep: true
    },
  },
  computed: {},
  created() {
    this.initValue()
  },
  mounted() {
    console.log(this.table, 'table')
    this.table.rows.forEach(item => {
      this.$set(item, 'columns', JSON.parse(JSON.stringify(this.table.columns)))
      item.columns.forEach(item2 => {
        // el-select绑定的数据为null，就会触发change事件，从而开启了表单校验
        if (item2.columnForm.type == 1) {
          if (item2.columnForm.multipleSelect) {
            this.$set(item2, 'value', (this.dataValue[item.id][item2.id] == null ? [] : this.dataValue[item.id][item2.id]))
          } else {
            this.$set(item2, 'value', (this.dataValue[item.id][item2.id] == null ? {} : this.dataValue[item.id][item2.id]))
          }
        } else {
          this.$set(item2, 'value', this.dataValue[item.id][item2.id])
          if(item2.columnForm.type == 4){
            this.$set(item2, 'value2', this.dataValue[item.id][item2.id])
          }
        }

      })
      this.tableData.rows.push(item)
    })
  },
  methods: {
    aaa() {
      this.$refs[this.item.vModel].validate((valid) => {
        if (valid) {
        } else {
          return false;
        }
      });
    },
    handlePreview(file) {
      console.log(file,'file')
      const elink = document.createElement('a')
      elink.style.display = 'none'
      if (!file.url) {
        file.url = URL.createObjectURL(file.raw);
      }
      elink.href = file.url
      var name = file.name.replace(/<[^>]+>/g, '')
      console.log(name,'eeeeeeeee')
      elink.download=name
      document.body.appendChild(elink)
      elink.click()
      document.body.removeChild(elink)
      // window.open(file.url)
    },
    handleExceed(col) {
      if (col.columnForm.multipleFile) {
        this.msgError('最多只能上传' + col.columnForm.fileNum + '个文件')
      } else {
        this.msgError('最多只能上传1个文件')
      }

    },
    handleUploadChange(fileList, rIndex, cIndex) {
      this.tableData.rows[rIndex].columns[cIndex].value2 = fileList
    },
    // 文件删除
    handleRemove(file, fileList, row, col, flag, rIndex, cIndex) {
      let tempList = jsonSimpleClone(this.dataValue[row][col])
      _.remove(tempList, function (item) {
        return item.uid === file.uid
      })
      this.tableData.rows[rIndex].columns[cIndex].value2 = fileList
      this.tableData.rows[rIndex].columns[cIndex].value = tempList
      this.dataValue[row][col] = tempList
      this.handleChange()
      this.flag = flag
      this.$nextTick(function () {
        this.$refs[this.item.vModel].validateField(this.flag)
      })
      this.$store.dispatch('form/uploadStatusMap', {
        [file.uid]: 3
      })
      if (axiosSourceMap.has(file.raw)) {
        axiosSourceMap.get(file.raw).abort()
      }
    },
    // 初始化矩阵value为二维数组
    initValue() {
      let initValue = {}
      this.table.rows.forEach(row => {
        initValue[row.id] = {}
        this.table.columns.forEach(col => {
          if (this.value[row.id] && this.value[row.id][col.id]) {
            initValue[row.id][col.id] = this.value[row.id][col.id]
          } else {
            initValue[row.id][col.id] = null
          }
        })
      })
      this.dataValue = initValue
      console.log(this.dataValue, 'this.dataValue')


    },
    handleChange() {
      this.value = this.dataValue
      this.$emit('change', this.dataValue)
    },
    httpRequest(item, row, col, flag, rIndex, cIndex) {
      const formData = new FormData()
      formData.append('file', item.file)

      this.$store.dispatch('form/uploadStatusMap', {
        [item.file.uid]: 1
      })
      const xhr = new XMLHttpRequest();
      xhr.timeout = 3600000
      xhr.onload = (e) => {
        if (xhr.status !== 200) {
          console.error(`Error ${xhr.status}: ${xhr.statusText}`);
        } else {
            const res = JSON.parse(xhr.responseText)
            const {data} = res
            let oldFileList = this.dataValue[row][col]
            if (!oldFileList) {
              oldFileList = []
            }
            oldFileList.push({
              name: item.file.name,
              url: data,
              uid:item.file.uid
            })
            this.tableData.rows[rIndex].columns[cIndex].value = oldFileList
            this.dataValue[row][col] = oldFileList
            this.handleChange()
            this.flag = flag
            this.$nextTick(function () {
              this.$refs[this.item.vModel].validateField(this.flag)
            })
            item.onSuccess()
        }

        this.$store.dispatch('form/uploadStatusMap', {
          [item.file.uid]: 2
        })
        axiosSourceMap.delete(item.file)
      }
      xhr.upload.onprogress = (e) => { //监听onprogress事件获取进度
        if (e.lengthComputable) {
          const percentComplete = e.loaded / e.total * 100;
          item.onProgress({status: 'uploading', percent: percentComplete})
        }
      };
      xhr.open('POST', `${item.action}?_=${new Date().getTime()}`);
      xhr.send(formData);
      axiosSourceMap.set(item.file, xhr)
    },

    handleSelectChange(val, col, rIndex, rowId, colId, value) {
      this.dataValue[rowId][colId] = value
      this.singleOrAll = true
      const {multipleOption, withExclusiveChoice, options} = col.columnForm
      if (val.length) {
        if (withExclusiveChoice) {
          const changeVal = val[val.length - 1]
          // 当前选中项的索引
          const isChecked = options.findIndex(
            (e) => e.value === changeVal.value
          )
          // 是否是互斥,不是返回-1，是的话返回对应的索引
          const isExclusive = multipleOption.findIndex(
            (e) => e.value === changeVal.value
          )
          // 选中 并且 互斥
          if (isChecked > -1 && isExclusive > -1) {
            options.forEach((item, index) => {
              if (index === isChecked) {
                item['disabled' + rIndex] = false
                // this.$set(item,'disabled'+rIndex,false)
              } else {
                // this.$set(item,'disabled'+rIndex,true)
                item['disabled' + rIndex] = true
              }
            })
          }
          // 选中 并且 不互斥
          if (isChecked > -1 && isExclusive === -1) {
            // 不是互斥的值
            const noExclusive = options.findIndex(
              (e) => e.value === changeVal.value
            )
            options.forEach((item, index) => {
              if (index === noExclusive) {
                // this.$set(item,'disabled'+rIndex,false)
                item['disabled' + rIndex] = false
              } else {
                multipleOption.forEach((item2, index2) => {
                  if (item.value == item2.value) {
                    // this.$set(item,'disabled'+rIndex,true)
                    item['disabled' + rIndex] = true
                  }
                })
              }
            })
            if (col.columnForm.min) {
              if (val.length < col.columnForm.min) {
                this.$message.warning("最少要选择" + col.columnForm.min + "个选项");
              }
            }
            if (col.columnForm.max) {
              if (val.length > col.columnForm.max) {
                this.$message.warning("最多只能选择" + col.columnForm.max + "个选项");
              }
            }
          }
        } else {
          if (col.columnForm.min) {
            if (val.length < col.columnForm.min) {
              this.$message.warning("最少要选择" + col.columnForm.min + "个选项");
            }
          }
          if (col.columnForm.max) {
            if (val.length > col.columnForm.max) {
              this.$message.warning("最多只能选择" + col.columnForm.max + "个选项");
            }
          }
        }

      } else {
        options.forEach((item, index) => {
          // this.$set(item,'disabled'+rIndex,false)
          item['disabled' + rIndex] = false
        })

      }
      this.handleChange()
    },
    handleInputChange(row, col, value) {
      this.dataValue[row][col] = value
      this.handleChange()
    },
  },

}
</script>

<style lang="scss" scoped>
.rt-container {
  padding: 20px;
  overflow-x: auto;
  overflow-y: hidden;
  width: 100%;

  .rt-table {
    width: 750px;
  }

  th, td {
    vertical-align: middle !important;
  }

  .el-input {
    width: 70%;
  }

  .el-select {
    width: 70% !important;
  }

  .leftAlign th, .leftAlign td {
    text-align: left;
  }

  .rightAlign th, .rightAlign td {
    text-align: right;
  }

  .centerAlign th, .centerAlign td {
    text-align: center;
  }
}


</style>
